#include "gradeconfigdialog.h"
#include "qcombobox.h"
#include "ui_gradeconfigdialog.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QFileDialog>
#include <QMessageBox>
#include <QAbstractButton>

GradeConfigDialog::GradeConfigDialog(const GradeRuleConfig& config, QWidget *parent)
    : QDialog(parent), ui(new Ui::GradeConfigDialog), m_currentConfig(config)
{
    ui->setupUi(this);

    // 更新缺陷名称映射（根据文档）
    m_defectNames = {
        {0, "OK"},
        {1, "Knot"},         // 结巴
        {2, "Unpolished"},   // 未抛光
        {3, "Defect"},       // 缺损
        {4, "MineralLine"},  // 矿物线
        {5, "Crack"},        // 开裂/裂缝
        {6, "DeadKnot"},     // 死结
        {7, "LiveKnot"}      // 活结
    };

    // 初始化缺陷表
    initDefectsTable();

    // 连接信号槽
    connect(ui->tableDefects, &QTableWidget::cellChanged,
            this, &GradeConfigDialog::onDefectCellChanged);
    connect(ui->spinCritical, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->comboHandrail, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &GradeConfigDialog::onHandrailTypeChanged);

    // 新增阈值连接
    connect(ui->spinKnotArea, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinUnpolishedDepth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinMineralLineCount, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinMinCutLength, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinMajorFor4, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinMajorFor3, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinMinorFor3, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);
    connect(ui->spinMinorFor2, QOverload<int>::of(&QSpinBox::valueChanged),
            this, &GradeConfigDialog::onThresholdChanged);

    ui->tableDefects->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableDefects->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableDefects->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableDefects->verticalHeader()->hide();

    // 设置扶手面料类型
    ui->comboHandrail->addItems({tr("Column Material"), tr("Handrail Material")});
    ui->comboHandrail->setCurrentIndex(m_currentConfig.isHandrail ? 1 : 0);

    // 设置初始阈值值
    ui->spinCritical->setValue(m_currentConfig.thresholds.criticalFaces);
    ui->spinKnotArea->setValue(m_currentConfig.thresholds.knotArea);
    ui->spinUnpolishedDepth->setValue(m_currentConfig.thresholds.unpolishedDepth);
    ui->spinMineralLineCount->setValue(m_currentConfig.thresholds.mineralLineCount);
    ui->spinMinCutLength->setValue(m_currentConfig.thresholds.minCutLength);
    ui->spinMajorFor4->setValue(m_currentConfig.thresholds.majorFacesFor4);
    ui->spinMajorFor3->setValue(m_currentConfig.thresholds.majorFacesFor3);
    ui->spinMinorFor3->setValue(m_currentConfig.thresholds.minorFacesFor3);
    ui->spinMinorFor2->setValue(m_currentConfig.thresholds.minorFacesFor2);

    // 更新阈值控件可见性
    updateThresholdsVisibility();
}

void GradeConfigDialog::initDefectsTable()
{
    ui->tableDefects->clearContents();
    ui->tableDefects->setRowCount(m_defectNames.size());
    ui->tableDefects->setShowGrid(true);

    int row = 0;
    for (auto it = m_defectNames.constBegin(); it != m_defectNames.constEnd(); ++it) {
        int id = it.key();
        QString name = it.value();

        // ID列
        auto *idItem = new QTableWidgetItem(QString::number(id));
        idItem->setFlags(idItem->flags() ^ Qt::ItemIsEditable);
        ui->tableDefects->setItem(row, 0, idItem);

        // 名称列
        auto *nameItem = new QTableWidgetItem(name);
        nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
        ui->tableDefects->setItem(row, 1, nameItem);

        // 等级选择
        auto *combo = new QComboBox();
        combo->addItems({tr("none"), tr("secondary"), tr("main"), tr("key")});
        int severity = m_currentConfig.defectSeverityMap.value(id, 0);
        combo->setCurrentIndex(severity);

        connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
                [this, id](int index) {
                    m_currentConfig.defectSeverityMap[id] = index;
                    updatePreview();
                });

        ui->tableDefects->setCellWidget(row, 2, combo);

        row++;
    }
}

void GradeConfigDialog::onDefectCellChanged(int row, int column)
{
    if (column != 2) return;

    int defectId = ui->tableDefects->item(row, 0)->text().toInt();
    auto* combo = qobject_cast<QComboBox*>(ui->tableDefects->cellWidget(row, 2));
    if (combo) {
        int severity = combo->currentIndex();
        m_currentConfig.defectSeverityMap[defectId] = severity;
        updatePreview();
    }
}

void GradeConfigDialog::onThresholdChanged()
{
    m_currentConfig.thresholds.criticalFaces = ui->spinCritical->value();
    m_currentConfig.thresholds.knotArea = ui->spinKnotArea->value();
    m_currentConfig.thresholds.unpolishedDepth = ui->spinUnpolishedDepth->value();
    m_currentConfig.thresholds.mineralLineCount = ui->spinMineralLineCount->value();
    m_currentConfig.thresholds.minCutLength = ui->spinMinCutLength->value();
    m_currentConfig.thresholds.majorFacesFor4 = ui->spinMajorFor4->value();
    m_currentConfig.thresholds.majorFacesFor3 = ui->spinMajorFor3->value();
    m_currentConfig.thresholds.minorFacesFor3 = ui->spinMinorFor3->value();
    m_currentConfig.thresholds.minorFacesFor2 = ui->spinMinorFor2->value();

    updatePreview();
}

void GradeConfigDialog::onHandrailTypeChanged(int index)
{
    m_currentConfig.isHandrail = (index == 1);
    updateThresholdsVisibility();
    updatePreview();
}

void GradeConfigDialog::updateThresholdsVisibility()
{
    bool isHandrail = m_currentConfig.isHandrail;

    // 柱面料特有设置
    ui->labelMineralLine->setVisible(!isHandrail);
    ui->spinMineralLineCount->setVisible(!isHandrail);
    ui->labelCriticalFaces->setVisible(!isHandrail);
    ui->spinCritical->setVisible(!isHandrail);
    ui->labelMajorFor4->setVisible(!isHandrail);
    ui->spinMajorFor4->setVisible(!isHandrail);
    ui->labelMajorFor3->setVisible(!isHandrail);
    ui->spinMajorFor3->setVisible(!isHandrail);
    ui->labelMinorFor3->setVisible(!isHandrail);
    ui->spinMinorFor3->setVisible(!isHandrail);
    ui->labelMinorFor2->setVisible(!isHandrail);
    ui->spinMinorFor2->setVisible(!isHandrail);

    // 扶手面料特有设置
    ui->labelColorSelection->setVisible(isHandrail);
    ui->comboColor->setVisible(isHandrail);

    // 通用设置
    ui->labelKnotArea->setVisible(true);
    ui->spinKnotArea->setVisible(true);
    ui->labelUnpolished->setVisible(true);
    ui->spinUnpolishedDepth->setVisible(true);
    ui->labelMinCut->setVisible(true);
    ui->spinMinCutLength->setVisible(true);
}

void GradeConfigDialog::loadDefaults()
{
    m_currentConfig = GradeRuleConfig(); // 使用默认值初始化

    // 更新UI
    initDefectsTable();
    ui->spinCritical->setValue(m_currentConfig.thresholds.criticalFaces);
    ui->spinKnotArea->setValue(m_currentConfig.thresholds.knotArea);
    ui->spinUnpolishedDepth->setValue(m_currentConfig.thresholds.unpolishedDepth);
    ui->spinMineralLineCount->setValue(m_currentConfig.thresholds.mineralLineCount);
    ui->spinMinCutLength->setValue(m_currentConfig.thresholds.minCutLength);
    ui->spinMajorFor4->setValue(m_currentConfig.thresholds.majorFacesFor4);
    ui->spinMajorFor3->setValue(m_currentConfig.thresholds.majorFacesFor3);
    ui->spinMinorFor3->setValue(m_currentConfig.thresholds.minorFacesFor3);
    ui->spinMinorFor2->setValue(m_currentConfig.thresholds.minorFacesFor2);
    ui->comboHandrail->setCurrentIndex(m_currentConfig.isHandrail ? 1 : 0);

    updateThresholdsVisibility();
    updatePreview();
}

void GradeConfigDialog::saveConfig()
{
    QString path = QFileDialog::getSaveFileName(this, "save config", "", "JSON file (*.json)");
    if (path.isEmpty()) return;

    QJsonObject root;
    QJsonObject defects;

    for (auto it = m_currentConfig.defectSeverityMap.constBegin();
         it != m_currentConfig.defectSeverityMap.constEnd();
         ++it) {
        defects[QString::number(it.key())] = it.value();
    }

    root["defects"] = defects;
    root["isHandrail"] = m_currentConfig.isHandrail;

    QJsonObject thresholds;
    thresholds["criticalFaces"] = m_currentConfig.thresholds.criticalFaces;
    thresholds["knotArea"] = m_currentConfig.thresholds.knotArea;
    thresholds["unpolishedDepth"] = m_currentConfig.thresholds.unpolishedDepth;
    thresholds["mineralLineCount"] = m_currentConfig.thresholds.mineralLineCount;
    thresholds["minCutLength"] = m_currentConfig.thresholds.minCutLength;
    thresholds["majorFacesFor4"] = m_currentConfig.thresholds.majorFacesFor4;
    thresholds["majorFacesFor3"] = m_currentConfig.thresholds.majorFacesFor3;
    thresholds["minorFacesFor3"] = m_currentConfig.thresholds.minorFacesFor3;
    thresholds["minorFacesFor2"] = m_currentConfig.thresholds.minorFacesFor2;
    root["thresholds"] = thresholds;

    QFile file(path);
    if (file.open(QIODevice::WriteOnly)) {
        file.write(QJsonDocument(root).toJson());
        QMessageBox::information(this, "Success", "Configuration saved successfully.");
    } else {
        QMessageBox::warning(this, "Error", "Failed to save configuration.");
    }
}
void GradeConfigDialog::loadConfig()
{
    QString path = QFileDialog::getOpenFileName(this, "load config", "", "JSON file (*.json)");
    if (path.isEmpty()) return;

    QFile file(path);
    if (file.open(QIODevice::ReadOnly)) {
        QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
        QJsonObject root = doc.object();

        // 解析缺陷映射
        QJsonObject defects = root["defects"].toObject();
        m_currentConfig.defectSeverityMap.clear();
        for (auto it = defects.begin(); it != defects.end(); ++it) {
            int id = it.key().toInt();
            int sev = it.value().toInt();
            m_currentConfig.defectSeverityMap[id] = sev;
        }

        // 解析面料类型
        if (root.contains("isHandrail")) {
            m_currentConfig.isHandrail = root["isHandrail"].toBool();
        }

        // 解析阈值
        QJsonObject th = root["thresholds"].toObject();
        if (th.contains("criticalFaces"))
            m_currentConfig.thresholds.criticalFaces = th["criticalFaces"].toInt();
        if (th.contains("knotArea"))
            m_currentConfig.thresholds.knotArea = th["knotArea"].toInt();
        if (th.contains("unpolishedDepth"))
            m_currentConfig.thresholds.unpolishedDepth = th["unpolishedDepth"].toDouble();
        if (th.contains("mineralLineCount"))
            m_currentConfig.thresholds.mineralLineCount = th["mineralLineCount"].toInt();
        if (th.contains("minCutLength"))
            m_currentConfig.thresholds.minCutLength = th["minCutLength"].toInt();
        if (th.contains("majorFacesFor4"))
            m_currentConfig.thresholds.majorFacesFor4 = th["majorFacesFor4"].toInt();
        if (th.contains("majorFacesFor3"))
            m_currentConfig.thresholds.majorFacesFor3 = th["majorFacesFor3"].toInt();
        if (th.contains("minorFacesFor3"))
            m_currentConfig.thresholds.minorFacesFor3 = th["minorFacesFor3"].toInt();
        if (th.contains("minorFacesFor2"))
            m_currentConfig.thresholds.minorFacesFor2 = th["minorFacesFor2"].toInt();

        initDefectsTable();
        ui->spinCritical->setValue(m_currentConfig.thresholds.criticalFaces);
        ui->spinKnotArea->setValue(m_currentConfig.thresholds.knotArea);
        ui->spinUnpolishedDepth->setValue(m_currentConfig.thresholds.unpolishedDepth);
        ui->spinMineralLineCount->setValue(m_currentConfig.thresholds.mineralLineCount);
        ui->spinMinCutLength->setValue(m_currentConfig.thresholds.minCutLength);
        ui->spinMajorFor4->setValue(m_currentConfig.thresholds.majorFacesFor4);
        ui->spinMajorFor3->setValue(m_currentConfig.thresholds.majorFacesFor3);
        ui->spinMinorFor3->setValue(m_currentConfig.thresholds.minorFacesFor3);
        ui->spinMinorFor2->setValue(m_currentConfig.thresholds.minorFacesFor2);
        ui->comboHandrail->setCurrentIndex(m_currentConfig.isHandrail ? 1 : 0);

        updateThresholdsVisibility();
        updatePreview();
        QMessageBox::information(this, "Success", "Configuration loaded successfully.");
    } else {
        QMessageBox::warning(this, "Error", "Failed to load configuration.");
    }
}
void GradeConfigDialog::updatePreview()
{
    // 创建示例数据测试当前配置
    struct TestCase {
        QString description;
        std::vector<unsigned int> defects[4]; // 四个面的缺陷
        int expectedGrade;
    };

    const std::vector<TestCase> testCases = {
        {"Perfect wood", {}, 1},
        {"Single-sided secondary defects", {{1}, {}, {}, {}}, 2},
        {"The main defects of both sides", {{2}, {2}, {}, {}}, 4},
        {"Mineral lines exceed limit", {{4,4,4}, {}, {}, {}}, 3} // 新增测试用例
    };

    QString previewText;
    for(const auto& tc : testCases) {
        // 转换测试数据到输入格式
        unsigned int* id[4] = {};
        unsigned int len[4] = {};
        for (int i = 0; i < 4; i++) {
            len[i] = tc.defects[i].size();
            if (len[i] > 0) {
                id[i] = new unsigned int[len[i]];
                std::copy(tc.defects[i].begin(), tc.defects[i].end(), id[i]);
            }
        }

        int actualGrade = classifyWoodGrade(id, len, m_currentConfig);
        previewText += QString("%1: Expect%2->Reality%3\n")
                           .arg(tc.description).arg(tc.expectedGrade).arg(actualGrade);

        // 清理内存
        for (int i = 0; i < 4; i++) {
            if (id[i]) delete[] id[i];
        }
    }

    ui->textPreview->setPlainText(previewText);
}

GradeConfigDialog::~GradeConfigDialog()
{
    delete ui;
}

int GradeConfigDialog::classifyWoodGrade(unsigned int **id, unsigned int *len, const GradeRuleConfig &config)
{
    int faceSeverity[4] = {0}; // 存储每个面的最高严重等级
    int knotCount[4] = {0};    // 每个面的结巴数量
    int mineralLineCount[4] = {0}; // 每个面的矿物线数量

    // 分析各个面的严重等级
    for (int face = 0; face < 4; face++) {
        for (int j = 0; j < len[face]; j++) {
            unsigned int defectId = id[face][j];
            auto it = config.defectSeverityMap.find(defectId);
            int severity = (it != config.defectSeverityMap.end()) ? it.value() : 0;

            // 特殊处理：结巴和矿物线需要计数
            if (defectId == 1 || defectId == 6 || defectId == 7) { // 结巴类型
                knotCount[face]++;
            } else if (defectId == 4) { // 矿物线
                mineralLineCount[face]++;
            }

            // 根据文档规则调整严重等级
            if (defectId == 2) { // 未抛光
                // 深度超过阈值提升等级
                if (severity > 0) severity++;
            }

            if (severity > faceSeverity[face]) {
                faceSeverity[face] = severity;
            }
        }

        // 应用文档中的特殊规则
        // 规则1: 结巴数量超过阈值提升等级
        if (knotCount[face] > config.thresholds.knotArea) {
            if (faceSeverity[face] < 2) faceSeverity[face] = 2;
        }

        // 规则2: 矿物线数量超过阈值提升等级
        if (mineralLineCount[face] > config.thresholds.mineralLineCount) {
            if (faceSeverity[face] < 2) faceSeverity[face] = 2;
        }
    }

    // 统计各等级缺陷面数量
    int critical = 0, major = 0, minor = 0;
    for (int i = 0; i < 4; i++) {
        if (faceSeverity[i] == 3) critical++;
        else if (faceSeverity[i] == 2) major++;
        else if (faceSeverity[i] == 1) minor++;
    }

    // 扶手面料特殊规则
    if (config.isHandrail) {
        // 规则: 上下宽面只要一面OK无缺陷为A料
        if (faceSeverity[0] == 0 || faceSeverity[1] == 0) {
            return 1; // A料
        }

        // 规则: 侧面结巴面积大于阈值
        if (faceSeverity[2] >= 2 || faceSeverity[3] >= 2) {
            return 2; // B料
        }

        // 规则: 宽面结巴数量超过阈值
        if (knotCount[0] + knotCount[1] > config.thresholds.knotArea) {
            return 2; // B料
        }

        return 1; // A料
    }
    // 柱面料规则
    else {
        // 应用可配置规则
        if (critical >= config.thresholds.criticalFaces) return 4;
        if (major >= config.thresholds.majorFacesFor4) return 4;
        if (major >= config.thresholds.majorFacesFor3) return 3;
        if (minor >= config.thresholds.minorFacesFor3) return 3;
        if (minor >= config.thresholds.minorFacesFor2) return 2;
        return 1;
    }
}

void GradeConfigDialog::on_Bt_defaults_clicked()
{
    loadDefaults();
}

void GradeConfigDialog::on_Bt_confirm_clicked()
{
    saveConfig();
}

void GradeConfigDialog::on_Bt_cancel_clicked()
{
    reject();
}
